#include "s3c2440.h"
#include "lcd.h"

volatile u32 lcd_buffer[LCD_HEIGHT][LCD_WIDTH];


void lcd_init(void)
{
    /* GPIO setting */
    GPCUP = 0xffffffff; /* disable pull-up */
    GPCCON = 0xaaaaaaaa; /* VD[7:0] LCD_LPCREVB LCD_LPCREV LCD_LPCOE VM VFRAME VLINE VCLK LEND */
    GPDUP = 0x00000000; /* enable pull-up */
    GPDCON = 0xaaaaaaaa; /* VD[23:8] */


    /* LCDCON setting */
    LCDCON1 = (CLKVAL << 8) | (MMODE << 7) | (PNRMODE << 5) | (BPPMODE << 1) | (ENVID << 0);
    LCDCON2 = (VBPD << 24) | (LINEVAL << 14) | (VFPD << 6) | (VSPW << 0);
    LCDCON3 = (HBPD << 19) | (HOZVAL << 8) | (HFPD << 0);
    LCDCON4 = (MVAL << 8) | (HSPW << 0);
    LCDCON5 = (BPP24BL << 12) | (INVVCLK << 10) | (INVVLINE << 9) | (INVVFRAME << 8) | (INVVD << 7) | (INVVDEN << 6) | (INVLEND << 4) | (ENLEND << 2) | (BSWP << 1) | (HWSWP << 0);

    /* LCDSADDR setting */
    LCDSADDR1 = (LCDBANK << 21) | (LCDBASEU << 0);
    LCDSADDR2 = (LCDBASEL << 0);
    LCDSADDR3 = (OFFSIZE << 11) | (PAGEWIDTH << 0);

    LCDINTMSK |= 0x3; /* MASK LCD Sub Interrupt */
    LPCSEL &= (~7); /* Disable LPC3480 */
    TPAL = 0; /* Disable Temp Palette */

    /* GPG4 is setted as LCD_PWREN */
    GPGUP = (GPGUP & (~(1 << 4))) | (1 << 4); /* Pull-up disable */
    GPGCON = (GPGCON & (~(3 << 8))) | (3 << 8); /* GPG4=LCD_PWREN */
    GPGDAT |= (1 << 4); /* GPG4 for power */

    /* Enable LCD POWER ENABLE */
    LCDCON5 = (LCDCON5 & (~(1 << 3))) | (PWREN<< 3);   /* PWREN */
    LCDCON5 = (LCDCON5 & (~(1 << 5))) | (INVPWREN<< 5);   /* INVPWREN */

    /* enable lcd output */
    LCDCON1 |= 1;
}


void lcd_set_pixel(u32 x, u32 y, color c)
{
    if (x < LCD_WIDTH && y < LCD_HEIGHT)
    {
        lcd_buffer[y][x] = c;
    }
}


void lcd_fill_backgroud(color c)
{
    u32 x, y;

    for (y = 0; y < LCD_HEIGHT; y++)
    {
        for (x = 0; x < LCD_WIDTH; x++)
        {
            lcd_buffer[y][x] = c;
        }
    }
}


void lcd_draw_hline(u32 x0, u32 x1, u32 y, color c)
{
    u32 x;
    for (x = x0; x <= x1; x++)
    {
        lcd_set_pixel(x, y, c);
    }
}


void lcd_draw_vline(u32 y0, u32 y1, u32 x, color c)
{
    u32 y;
    for (y = y0; y <= y1; y++)
    {
        lcd_set_pixel(x, y, c);
    }
}


void lcd_draw_rect(u32 x0, u32 y0, u32 x1, u32 y1, color c)
{
    lcd_draw_hline(x0, x1, y0, c);
    lcd_draw_hline(x0, x1, y1, c);
    lcd_draw_vline(y0, y1, x0, c);
    lcd_draw_vline(y0, y1, x1, c);
}
